package com.qiaofang.collectmanage.dao.util;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.qiaofang.collectmanage.constants.SecretaryCollectTypeEnum;
import com.qiaofang.collectmanage.dao.domain.Secretary;
import com.qiaofang.collectmanage.dao.domain.SecretaryExtend;
import com.qiaofang.collectmanage.stub.request.SecretaryRequest;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.net.ssl.SSLContext;
import java.security.MessageDigest;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author jf.sun
 */
public class SecretaryDaoConvert {
    private static final Logger logger = LoggerFactory.getLogger(SecretaryDaoConvert.class);
    /**
     * 获取登录cookie
     * @param url 登录url
     * @param phone 登录账号
     * @param userPwd 登录密码
     * @return
     */
    public String getCookie (String url, String phone, String userPwd) {
        url = url.replace("{phone}",phone).replace("{userPwd}",userPwd);
        HttpResponse httpResponse = doPost(url, "", "");
        Header[] headers = httpResponse.getHeaders("Set-Cookie");
        String cookie = "";
        for (Header header : headers) {
            String headerStr = String.valueOf(header.getValue());
            if (headerStr.contains("JSESSIONID") || headerStr.contains("userInfo")) {
                String [] array = headerStr.split(";");
                cookie += array[0] + ";";
            }
        }
        return cookie;
    }

    /**
     * 根据城市索引值，获取城市名称
     * @param cityIndex 城市索引值
     * @return 城市名称
     */
    public String getCityName(int cityIndex) {
        String cityName = "";
        switch(cityIndex){
            case 21:
                cityName = "上海";
                break;
            default:
                break;
        }
        return cityName;
    }

    /**
     * @param requestParam 请求参数
     * @param detailUrl 爬取得URL
     * @param collectType 爬取类型 出租，出售
     * @param charset 页面编码
     * @param cookie 登录cookie
     * @return
     * @throws Exception
     */
    public List<SecretaryExtend> processHouseInfo (String requestParam, String detailUrl, String collectType, String charset, String cookie, String belonger, String collectHouseType) {
        List<SecretaryExtend> secretaryExtendList = new ArrayList<>();
        HttpResponse httpResponse = doPost(detailUrl, requestParam, cookie);
        if(httpResponse == null) {
            return secretaryExtendList;
        }
        HttpEntity resEntity = httpResponse.getEntity();
        if(resEntity == null){
            return secretaryExtendList;
        }
        String responseStr;
        try {
            responseStr = EntityUtils.toString(resEntity, charset);
        } catch (Exception exception) {
            logger.error("exception : {}", exception);
            responseStr = "";
        }
        if(StringUtils.isBlank(responseStr)){
            return secretaryExtendList;
        }
        JSONObject jsonObject = JSONObject.parseObject(responseStr);
        JSONArray jsonArray = jsonObject.getJSONArray("list");
        if (jsonArray == null || jsonArray.size() <= 0) {
            logger.info("jsonObject : {}", jsonObject);
            return secretaryExtendList;
        }
        for (int i=0; i < jsonArray.size(); i++) {
            Secretary secretary = new Secretary();
            JSONObject jsonObject2 = jsonArray.getJSONObject(i);
            String title = jsonObject2.getString("title");
            secretary.setTitle(title);
            String url = jsonObject2.getString("url");
            secretary.setTitleLink(url);
            String webName = jsonObject2.getString("webName");
            if("第一时间房产网".equals(webName)){
                webName="第1时间房源网";
            }else if("搜房网".equals(webName)){
                webName="房天下";
            }
            secretary.setSource(webName);
            String createTime = jsonObject2.getString("creatime");
            secretary.setCreateTime(DateUtils.convertTimeToString(createTime));
            String updateTime = jsonObject2.getString("updatetime");
            secretary.setUpdateTime(DateUtils.convertTimeToString(updateTime));
            int cityIndex = jsonObject2.getInteger("city");
            String city = getCityName(cityIndex);
            secretary.setCity(city);
            secretary.setCollectType(collectType);
            secretary.setBelonger(belonger);
            secretary.setCollectHouseType(collectHouseType);
            String id = getJsonObjectId(title, url, createTime, updateTime, webName);
            SecretaryExtend secretaryExtend = new SecretaryExtend();
            secretaryExtend.setId(id);
            secretaryExtend.setSecretary(secretary);
            secretaryExtendList.add(secretaryExtend);

        }
        if (secretaryExtendList == null || secretaryExtendList.size() <= 0) {
            return secretaryExtendList;
        }
        return secretaryExtendList;
    }

    public static String getJsonObjectId(String title, String url, String createTime, String updateTime, String webName) {
        String requestId = title + url + createTime + updateTime + webName;
        String response = md5(requestId);
        return response;
    }

    /**
     * @param secretaryRequest 请求参数
     * @throws Exception
     */
    public List<SecretaryExtend> executeCrawlerTask(SecretaryRequest secretaryRequest) throws Exception {
        int defaultPage = Integer.valueOf(secretaryRequest.getDefaultPage());
        // 页面编码
        String pageCharset = secretaryRequest.getPageCharset();
        // 登录手机号
        String loginName = secretaryRequest.getLoginName();
        // 登录密码
        String userPass = secretaryRequest.getLoginPass();
        // 登录链接
        String loginUrl = secretaryRequest.getLoginUrl();
        // 爬取链接
        String detailUrl = secretaryRequest.getDetailUrl();
        // 获取collectType
        String collectType = secretaryRequest.getCollectType();
        // 两次请求间隔时间 单位为毫秒
        int waitTime = Integer.valueOf(secretaryRequest.getWaitTime());
        int postType = (SecretaryCollectTypeEnum.RENT.getName().equals(collectType)) ? SecretaryCollectTypeEnum.RENT.getIndex() : SecretaryCollectTypeEnum.SALE.getIndex();
        String belonger = secretaryRequest.getBelonger();
        String collectHouseType = secretaryRequest.getCollectHouseType();
        String cookie = getCookie (loginUrl, loginName, userPass);
        List<SecretaryExtend> secretaryExtendListAll = new ArrayList<>();
        for (int pageNum = defaultPage; pageNum > 0; pageNum--) {
            String requestParam = secretaryRequest.getDetailParam();
            requestParam = requestParam.replace("{pageNow}",pageNum + "");
            requestParam = requestParam.replace("{postType}",postType + "");
            requestParam = requestParam.replace("{houseType}",collectHouseType+"");
            String nowDate = DateUtils.formatDate(new Date(), DateUtils.YYYY_MM_DD);
            String startTime = (StringUtils.isBlank(secretaryRequest.getStartTime())) ? nowDate : secretaryRequest.getStartTime();
            String endTime = (StringUtils.isBlank(secretaryRequest.getEndTime())) ? nowDate : secretaryRequest.getEndTime();
            requestParam = requestParam.replace("{startTime}",startTime + "");
            requestParam = requestParam.replace("{endTime}",endTime + "");
            Thread.sleep(waitTime);
            List<SecretaryExtend> secretaryExtendList = processHouseInfo(requestParam, detailUrl, collectType, pageCharset, cookie, belonger, collectHouseType);
            if (secretaryExtendList != null ) {
                logger.info("当前页{},爬取条数{}", pageNum,secretaryExtendList.size());
            }
            secretaryExtendListAll.addAll(secretaryExtendList);
        }
        return secretaryExtendListAll;
    }

    /**
     * 请求配置，设置链接超时和读取超时
     */
    private static final RequestConfig REQUEST_CONFIG = RequestConfig.custom().setConnectTimeout(30000).setSocketTimeout(30000).build();
    /**
     * https策略，绕过安全检查
     */
    private static CloseableHttpClient getSingleSSLConnection() throws Exception {
        try {
            SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
                @Override
                public boolean isTrusted(X509Certificate[] paramArrayOfX509Certificate, String paramString) {
                    return true;
                }
            }).build();
            SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext);
            return HttpClients.custom().setSSLSocketFactory(sslConnectionSocketFactory).setDefaultRequestConfig(REQUEST_CONFIG).build();
        } catch (Exception e) {
            throw e;
        }
    }

    /**
     * @param url 请求url
     * @param requestParam 请求参数
     * @param cookie 请求 cookie
     * @return
     */
    public static HttpResponse doPost(String url, String requestParam, String cookie){
        CloseableHttpClient httpClient;
        CloseableHttpResponse response = null;
        try{
            httpClient = getSingleSSLConnection();
            HttpPost httpPost = new HttpPost(url);
            httpPost.addHeader("Cookie", cookie);
            httpPost.addHeader("X-Requested-With", "XMLHttpRequest");
            httpPost.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36");
            httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded");
            StringEntity se = new StringEntity(requestParam);
            se.setContentType("text/json");
            se.setContentEncoding(new BasicHeader("Content-Type", "application/json"));
            httpPost.setEntity(se);
            for (int i = 1; i <= 3; i++) {
                response = httpClient.execute(httpPost);
                if (response != null) {
                    break;
                }
                if (i == 3) {
                    break;
                }
            }
        } catch(Exception ex){
            ex.printStackTrace();
        }
        return response;
    }

    private static String md5 (String sourceStr) {
        String result = "";
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(sourceStr.getBytes());
            byte[] newByte = md.digest();
            int i;
            StringBuffer buf = new StringBuffer();
            for (int offset = 0; offset < newByte.length; offset++) {
                i = newByte[offset];
                if (i < 0) {
                    i += 256;
                }
                if (i < 16) {
                    buf.append("0");
                }
                buf.append(Integer.toHexString(i));
            }
            result = buf.toString().substring(8, 24);
        } catch (Exception e) {
            logger.info("异常信息{}", e);
        }
        return result;
    }
}

